﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Settlements.Locations.LocationComplex
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.Core;
using TaleWorlds.Localization;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Settlements.Locations
{
  public class LocationComplex
  {
    [SaveableField(1)]
    private readonly Dictionary<string, Location> _locations;

    internal static void AutoGeneratedStaticCollectObjectsLocationComplex(
      object o,
      List<object> collectedObjects)
    {
      ((LocationComplex) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this._locations);
    }

    internal static object AutoGeneratedGetMemberValue_locations(object o)
    {
      return (object) ((LocationComplex) o)._locations;
    }

    public static LocationComplex Current
    {
      get
      {
        return PlayerEncounter.LocationEncounter != null ? PlayerEncounter.LocationEncounter.Settlement.LocationComplex : (LocationComplex) null;
      }
    }

    public static bool CanAlways(LocationCharacter locationCharacter, Location location) => true;

    public static bool CanNever(LocationCharacter locationCharacter, Location location) => false;

    public static bool CanIfHero(LocationCharacter locationCharacter, Location location)
    {
      return locationCharacter.Character.IsHero;
    }

    public static bool CanIfDay(LocationCharacter locationCharacter, Location location)
    {
      return !Campaign.Current.IsNight;
    }

    public static bool CanIfPriceIsPaid(LocationCharacter locationCharacter, Location location)
    {
      switch (location.StringId)
      {
        case "lordshall":
          return Campaign.Current.Models.BribeCalculationModel.GetBribeToEnterLordsHall(Settlement.CurrentSettlement) == 0;
        case "prison":
          return Campaign.Current.Models.BribeCalculationModel.GetBribeToEnterDungeon(Settlement.CurrentSettlement) == 0;
        default:
          return false;
      }
    }

    public static bool CanIfGrownUpMaleOrHero(
      LocationCharacter locationCharacter,
      Location location)
    {
      return LocationComplex.CanIfMaleOrHero(locationCharacter, location) && (double) locationCharacter.Character.Age >= (double) Campaign.Current.Models.AgeModel.HeroComesOfAge;
    }

    public static bool CanIfMaleOrHero(LocationCharacter locationCharacter, Location location)
    {
      return !locationCharacter.Character.IsFemale || locationCharacter.Character.IsHero;
    }

    public static bool CanIfSettlementAccessModelLetsPlayer(
      LocationCharacter locationCharacter,
      Location location)
    {
      return Campaign.Current.Models.SettlementAccessModel.CanMainHeroAccessLocation(Settlement.CurrentSettlement, location.StringId, out bool _, out TextObject _);
    }

    public LocationComplex() => this._locations = new Dictionary<string, Location>();

    public LocationComplex(LocationComplexTemplate complexTemplate)
      : this()
    {
      foreach (Location location in complexTemplate.Locations)
        this._locations.Add(location.StringId, new Location(location, this));
      foreach (KeyValuePair<string, string> passage in complexTemplate.Passages)
        this.AddPassage(this.GetLocationWithId(passage.Key), this.GetLocationWithId(passage.Value));
    }

    public LocationComplex(LocationComplex complex)
      : this()
    {
      List<KeyValuePair<string, string>> keyValuePairList = new List<KeyValuePair<string, string>>();
      foreach (Location listOfLocation in complex.GetListOfLocations())
      {
        this._locations.Add(listOfLocation.StringId, new Location(listOfLocation, this));
        foreach (Location locationsOfPassage in listOfLocation.LocationsOfPassages)
        {
          if (!keyValuePairList.Contains(new KeyValuePair<string, string>(locationsOfPassage.StringId, listOfLocation.StringId)) && !keyValuePairList.Contains(new KeyValuePair<string, string>(listOfLocation.StringId, locationsOfPassage.StringId)))
            keyValuePairList.Add(new KeyValuePair<string, string>(listOfLocation.StringId, locationsOfPassage.StringId));
        }
      }
      foreach (KeyValuePair<string, string> keyValuePair in keyValuePairList)
        this.AddPassage(this.GetLocationWithId(keyValuePair.Key), this.GetLocationWithId(keyValuePair.Value));
    }

    public void Initialize(LocationComplexTemplate complexTemplate)
    {
      foreach (Location location1 in complexTemplate.Locations)
      {
        Location location2 = this.GetLocationWithId(location1.StringId);
        if (location2 == null)
        {
          location2 = new Location(location1, this);
          this._locations.Add(location1.StringId, location2);
        }
        location2?.Initialize(location1, this);
      }
      foreach (string str in this._locations.Keys.ToList<string>())
      {
        Location locationWithId = this.GetLocationWithId(str);
        if (locationWithId == null || !locationWithId.IsInitialized)
          this._locations.Remove(str);
      }
      foreach (KeyValuePair<string, string> passage in complexTemplate.Passages)
        this.AddPassage(this.GetLocationWithId(passage.Key), this.GetLocationWithId(passage.Value));
    }

    public void AddPassage(Location firstLocation, Location secondLocation)
    {
      firstLocation.AddPassageToLocation(secondLocation);
      secondLocation.AddPassageToLocation(firstLocation);
    }

    public void ChangeLocation(
      LocationCharacter locationCharacter,
      Location fromLocation,
      Location toLocation)
    {
      fromLocation?.RemoveLocationCharacter(locationCharacter);
      toLocation?.AddCharacter(locationCharacter);
      toLocation?.OnAIChangeLocation(fromLocation);
      if (CampaignMission.Current == null || toLocation != null && toLocation != CampaignMission.Current.Location)
        return;
      PlayerEncounter.LocationEncounter.OnCharacterLocationChanged(locationCharacter, fromLocation, toLocation);
    }

    public IEnumerable<LocationCharacter> GetListOfCharactersInLocation(string locationName)
    {
      foreach (LocationCharacter character in this._locations[locationName].GetCharacterList())
        yield return character;
    }

    public IList<LocationCharacter> GetListOfCharacters()
    {
      List<LocationCharacter> first = new List<LocationCharacter>();
      foreach (KeyValuePair<string, Location> location in this._locations)
        first = first.Concat<LocationCharacter>(location.Value.GetCharacterList()).ToList<LocationCharacter>();
      return (IList<LocationCharacter>) first.AsReadOnly();
    }

    public IEnumerable<Location> GetListOfLocations()
    {
      foreach (KeyValuePair<string, Location> location in this._locations)
        yield return location.Value;
    }

    public void AgentPassageUsageTick()
    {
      if (CampaignMission.Current.Mode == MissionMode.Stealth)
        return;
      List<LocationCharacter> locationCharacterList = new List<LocationCharacter>();
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        if (location.Value != CampaignMission.Current.Location && location.Value.CanAIExit((LocationCharacter) null))
        {
          foreach (LocationCharacter character in location.Value.GetCharacterList())
          {
            if (!character.FixedLocation)
              locationCharacterList.Add(character);
          }
        }
      }
      if (locationCharacterList.Count <= 0)
        return;
      LocationCharacter locationCharacter = locationCharacterList[MBRandom.RandomInt(locationCharacterList.Count)];
      Location locationOfCharacter = this.GetLocationOfCharacter(locationCharacter);
      int maxValue = 0;
      foreach (Location locationsOfPassage in locationOfCharacter.LocationsOfPassages)
      {
        if (locationsOfPassage.CanAIEnter(locationCharacter) && locationsOfPassage.CharacterCount < locationsOfPassage.ProsperityMax)
          maxValue += locationsOfPassage.ProsperityMax;
      }
      if (maxValue <= 0)
        return;
      int num = MBRandom.RandomInt(maxValue);
      Location toLocation = (Location) null;
      foreach (Location locationsOfPassage in locationOfCharacter.LocationsOfPassages)
      {
        if (locationsOfPassage.CanAIEnter(locationCharacter) && locationsOfPassage.CharacterCount < locationsOfPassage.ProsperityMax)
        {
          num -= locationsOfPassage.ProsperityMax;
          if (num < 0)
            toLocation = locationsOfPassage;
        }
      }
      this.ChangeLocation(locationCharacter, locationOfCharacter, toLocation);
    }

    public Location GetLocationOfCharacter(LocationCharacter character)
    {
      Location locationOfCharacter = (Location) null;
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        if (location.Value.ContainsCharacter(character))
          locationOfCharacter = location.Value;
      }
      return locationOfCharacter;
    }

    public Location GetLocationOfCharacter(Hero hero)
    {
      Location locationOfCharacter = (Location) null;
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        if (location.Value.ContainsCharacter(hero))
        {
          locationOfCharacter = location.Value;
          break;
        }
      }
      return locationOfCharacter;
    }

    public LocationCharacter GetLocationCharacterOfHero(Hero hero)
    {
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        LocationCharacter locationCharacter = location.Value.GetLocationCharacter(hero);
        if (locationCharacter != null)
          return locationCharacter;
      }
      return (LocationCharacter) null;
    }

    public LocationCharacter GetFirstLocationCharacterOfCharacter(CharacterObject character)
    {
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        foreach (LocationCharacter character1 in location.Value.GetCharacterList())
        {
          if (character1.Character == character)
            return character1;
        }
      }
      return (LocationCharacter) null;
    }

    public void RemoveCharacterIfExists(Hero hero)
    {
      this.GetLocationOfCharacter(hero)?.RemoveCharacter(hero);
    }

    public void RemoveCharacterIfExists(LocationCharacter locationCharacter)
    {
      this.GetLocationOfCharacter(locationCharacter)?.RemoveLocationCharacter(locationCharacter);
    }

    public void ClearTempCharacters()
    {
      foreach (KeyValuePair<string, Location> location in this._locations)
        location.Value.RemoveAllCharacters();
    }

    public Location GetLocationWithId(string id)
    {
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        if (location.Key == id)
          return location.Value;
      }
      return (Location) null;
    }

    public string GetScene(string stringId, int upgradeLevel)
    {
      return this.GetLocationWithId(stringId).GetSceneName(upgradeLevel);
    }

    public LocationCharacter FindCharacter(IAgent agent)
    {
      LocationCharacter character = (LocationCharacter) null;
      foreach (KeyValuePair<string, Location> location in this._locations)
      {
        character = location.Value.GetLocationCharacter(agent.Origin);
        if (character != null)
          break;
      }
      return character;
    }

    public IEnumerable<Location> FindAll(Func<string, bool> predicate)
    {
      return this._locations.Where<KeyValuePair<string, Location>>((Func<KeyValuePair<string, Location>, bool>) (kv => predicate(kv.Key))).Select<KeyValuePair<string, Location>, Location>((Func<KeyValuePair<string, Location>, Location>) (kv => kv.Value));
    }
  }
}
